package com.example.dl645.config;

import com.example.dl645.model.MeterData;
import com.example.dl645.protocol.strategy.Ddzy22cParseStrategy;
import com.example.dl645.protocol.strategy.DtzyGfParseStrategy;
import com.example.dl645.protocol.strategy.MeterParseStrategy;
import com.example.dl645.service.ConcentratorConnectionManager;
import io.netty.channel.ChannelHandler.Sharable;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.time.LocalDateTime;
import java.util.Arrays;
import java.util.concurrent.ThreadLocalRandom;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * 集中器消息处理器（按电表型号分策略解析）
 */
@Sharable
@Component
public class ConcentratorServerHandler extends ChannelInboundHandlerAdapter {

    @Autowired
    private ConcentratorConnectionManager connectionManager;

    // 线程本地存储：当前连接的集中器ID
    private final ThreadLocal<String> currentConcentratorId = new ThreadLocal<>();

    @Override
    public void channelActive(ChannelHandlerContext ctx) {
        String clientAddr = ctx.channel().remoteAddress().toString();
        System.out.println("🔌 集中器连接：" + clientAddr);
        String concentratorId = "CONCENTRATOR-" + System.currentTimeMillis() + "-" + ThreadLocalRandom.current().nextInt(1000);
        currentConcentratorId.set(concentratorId);
        connectionManager.register(concentratorId, ctx.channel());
        System.out.println("📝 集中器[" + concentratorId + "]注册成功，当前连接数：" + connectionManager.getOnlineCount());
    }

    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) {
        String concentratorId = currentConcentratorId.get();
        if (concentratorId == null) {
            System.err.println("❌ 未获取到集中器ID，忽略数据");
            return;
        }

        byte[] data = (byte[]) msg;
        int frameLength = data.length;
        String hexData = bytesToHex(data);
        System.out.println("📥 收到集中器[" + concentratorId + "]数据，长度=" + frameLength + "，内容=" + hexData);

        try {
            int frameHeader2Index = findFrameHeader2(data);
            if (frameHeader2Index == -1) {
                System.err.println("❌ 未找到帧头2，无法解析");
                return;
            }
            String meterModel = getMeterModelByLength(frameLength);
            if (meterModel == null) {
                System.err.println("❌ 不支持的帧长度：" + frameLength + "字节，忽略解析");
                return;
            }
            System.out.println("ℹ️ 按帧长度匹配电表型号：" + meterModel);
            if (meterModel.equals("heart")){
                System.out.println("心跳包处理完成");
            } else if (meterModel.equals("DTZY-GF") || meterModel.equals("DDZY22C")) {
                handleNormalResponse(data, concentratorId, frameHeader2Index, meterModel);
                System.out.println("DTZY/DDZY 数据包处理完成");
            }

        } catch (Exception e) {
            System.err.println("❌ channelRead 处理过程中发生异常: " + e.getMessage());
            e.printStackTrace();
        } finally {
            System.out.println("✅ channelRead for [" + concentratorId + "] finished execution.");
        }
    }

    /**
     * 按帧长度区分电表型号（51→DTZY-GF，53→DDZY22C）
     */
    private String getMeterModelByLength(int frameLength) {
        if (frameLength == 51) {
            return "DTZY-GF";
        } else if (frameLength == 53) {
            return "DDZY22C";
        } else if (frameLength == 20) {
            return "heart";
        } else {
            return null;
        }
    }

    private int findFrameHeader2(byte[] data) {
        int frameHeaderCount = 0;
        for (int i = 0; i < data.length; i++) {
            if (data[i] == (byte) 0x68) {
                frameHeaderCount++;
                if (frameHeaderCount == 2) {
                    return i;
                }
            }
        }
        return -1;
    }

    /**
     * 处理正常响应帧（按电表型号分策略解析）
     */
    private void handleNormalResponse(byte[] data, String concentratorId, int frameHeader2Index, String meterModel) {
        String hexData = bytesToHex(data);
        try {
            byte[] dataField = extractDataFieldByModel(data, frameHeader2Index, meterModel);
            MeterParseStrategy strategy = getStrategyByModel(meterModel);
            if (strategy == null) {
                throw new RuntimeException("未找到" + meterModel + "的解析策略");
            }
            MeterData meterData = strategy.parse(dataField);
            meterData.setConcentratorId(concentratorId);
            meterData.setMeterId(extractMeterAddress(data, frameHeader2Index));
            meterData.setCollectTime(LocalDateTime.now().toString());
            System.out.println("✅ " + meterModel + "解析成功：" + meterData);

        } catch (Exception e) {
            System.err.println("❌ 解析失败：" + e.getMessage() + "，数据：" + hexData);
        }
    }

    /**
     * 按电表型号差异化提取数据域
     */
    private byte[] extractDataFieldByModel(byte[] data, int frameHeader2Index, String meterModel) {
        int dataLenIndex;
        int dataStart;
        int targetDataEnd;
        int actualDataEnd;

        switch (meterModel) {
            case "DTZY-GF":
                dataLenIndex = frameHeader2Index + 2;
                dataStart = dataLenIndex + 1;
                targetDataEnd = 48;
                actualDataEnd = Math.min(targetDataEnd, data.length - 2);
                break;
            case "DDZY22C":
                dataLenIndex = frameHeader2Index + 2;
                dataStart = dataLenIndex + 1;
                targetDataEnd = 58;
                actualDataEnd = Math.min(targetDataEnd, data.length - 2);
                break;
            default:
                throw new RuntimeException("不支持的电表型号：" + meterModel);
        }
        if (dataStart >= data.length) {
            throw new RuntimeException(meterModel + "数据域起始索引越界（" + dataStart + "）");
        }
        int dataFieldLength = actualDataEnd - dataStart + 1;
        System.out.println("ℹ️ " + meterModel + "数据域范围：" + dataStart + "~" + actualDataEnd + "（共" + dataFieldLength + "字节）");
        return Arrays.copyOfRange(data, dataStart, actualDataEnd + 1);
    }

    private MeterParseStrategy getStrategyByModel(String meterModel) {
        if ("DTZY-GF".equals(meterModel)) {
            return new DtzyGfParseStrategy();
        } else if ("DDZY22C".equals(meterModel)) {
            return new Ddzy22cParseStrategy();
        } else {
            return null;
        }
    }


    /**
     * 校验是否为合法DL/T 645帧
     */
    private boolean isValidDl645Frame(byte[] data, AtomicInteger frameHeader2IndexHolder) {
        if (data.length < 12) {
            System.out.println("ℹ️ 帧长度不足12字节（实际：" + data.length + "），非合法帧");
            return false;
        }
        int frameHeader1Index = -1;
        for (int i = 0; i < data.length; i++) {
            if (data[i] == (byte) 0x68) {
                frameHeader1Index = i;
                break;
            }
        }
        if (frameHeader1Index == -1) {
            System.out.println("ℹ️ 未找到帧头1（68H），非合法帧");
            return false;
        }
        System.out.println("ℹ️ 动态找到帧头1，索引：" + frameHeader1Index);

        int expectedFrameHeader2Index = frameHeader1Index + 1 + 6;
        int frameHeader2Index = -1;
        int startSearchIndex = Math.max(expectedFrameHeader2Index - 1, frameHeader1Index + 1);
        int endSearchIndex = Math.min(expectedFrameHeader2Index + 1, data.length - 1);
        for (int i = startSearchIndex; i <= endSearchIndex; i++) {
            if (data[i] == (byte) 0x68) {
                frameHeader2Index = i;
                break;
            }
        }
        if (frameHeader2Index == -1) {
            return false;
        }
        if (data[data.length - 1] != (byte) 0x16) {
            return false;
        }
        frameHeader2IndexHolder.set(frameHeader2Index);
        return true;
    }
    /**
     * 提取电表地址（6字节，转十六进制）
     */
    private String extractMeterAddress(byte[] data, int frameHeader2Index) {
        int frameHeader1Index = -1;
        for (int i = 0; i < frameHeader2Index; i++) {
            if (data[i] == (byte) 0x68) {
                frameHeader1Index = i;
                break;
            }
        }
        byte[] addressField = Arrays.copyOfRange(data, frameHeader1Index + 1, frameHeader2Index);
        return bytesToHex(addressField);
    }

    /**
     * 字节数组转十六进制字符串
     */
    private String bytesToHex(byte[] bytes) {
        StringBuilder sb = new StringBuilder();
        for (byte b : bytes) {
            sb.append(String.format("%02X ", b));
        }
        return sb.toString().trim();
    }

    @Override
    public void channelInactive(ChannelHandlerContext ctx) throws Exception {
        String concentratorId = currentConcentratorId.get();
        if (concentratorId != null) {
            System.out.println("🔌 集中器[" + concentratorId + "]断开连接。");
            connectionManager.unregister(concentratorId);
            System.out.println("📝 集中器[" + concentratorId + "]注销成功，当前连接数：" + connectionManager.getOnlineCount());
            currentConcentratorId.remove();
        } else {
            System.out.println("🔌 未知集中器断开连接。");
        }
        super.channelInactive(ctx);
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
        String concentratorId = currentConcentratorId.get();
        System.err.println("❌ 集中器[" + concentratorId + "]通信异常：" + cause.getMessage());
        ctx.close();
    }
}